<?php

/**
 * 采购单采购单
 */

namespace app\admin\service;

use app\admin\model\Product as ProductModel;
use app\admin\model\PurchasePaymentOrder;
use app\admin\model\PurchaseReceiptDetails;
use app\common\Calculate;
use app\common\ExchangeRateHostAPI;
use Exception;
use think\facade\Db;
use app\admin\model\PurchaseOrders as PurchaseModel;
use app\admin\model\PurchaseOrdersDetail as PurchaseOrdersDetailModel;
use app\admin\model\Inventory as InventoryModel;
use app\admin\model\Operator as OperatorModel;
use app\admin\model\Supplier as SupplierModel;

use app\admin\model\Order;
use app\admin\model\WholesalOrder;
use app\common\Common;
use app\common\service\CompleteNotificationService;

class Purchase extends BaseService
{

    /**
     * 获取采购单列表
     * @param $param
     * @param $page
     * @param $limit
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList($param = [], $page = 1, $limit = 10)
    {
        $where = [['is_del', '=', 0]];
        $arrData = ['code' => 0, 'message' => 'success'];
        if ($param['name']) {
            $where[] = ['name', 'like', '%' . $param['name'] . '%'];
        }
        if ($param['purchase_no']) {
            $where[] = ['purchase_no', 'like', '%' . $param['purchase_no'] . '%'];
        }
        if ($param['pay_status']) {
            $pay_status_arr = explode(',', $param['pay_status']);
            $where[] = ['pay_status', 'in', $pay_status_arr];
        }
        if ($param['status']) {
            $where[] = ['status', '=', $param['status']];
        }
        if ($param['start_date']) {
            $where[] = ['create_time', '>', $param['start_date']];
        }
        if ($param['end_date']) {
            $where[] = ['create_time', '<=', $param['end_date']];
        }
        if ($param['owner']) {
            $where[] = ['owner', '=', $param['owner']];
        }
        if ($param['supid']) {
            $where[] = ['supid', '=', $param['supid']];
        }
        if ($param['type']) {
            $where[] = ['type', '=', $param['type']];
        }
        if ($param['contract_no']) {
            $where[] = ['contract_no', 'like', '%' . $param['contract_no'] . '%'];
        }

        // === 优化点1：将 is_futures 整合到主查询条件 ===
        if (isset($param['is_futures']) && $param['is_futures'] !== null) {
            $purchaseNos = \app\admin\model\PurchaseReceiptDetails::alias('prd')
                ->join('inventory inv', 'prd.inventory_id = inv.id')
                ->where('inv.is_futures', $param['is_futures'])
                ->column('prd.purchase_no');

            if (!empty($purchaseNos)) {
                $where[] = ['purchase_no', 'in', $purchaseNos];
            } else {
                $where[] = ['purchase_no', '=', '']; // 无匹配结果
            }
        }
        $oPurchaseModel = PurchaseModel::alias('po')->where($where);

        if ($param['product_id']) {
            $oPurchaseModel->join('db_purchase_orders_detail pod', 'pod.orderid = po.id and pod.productid in (' . $param['product_id'] . ')');
        }

        $total = $oPurchaseModel->count();
        $result = $oPurchaseModel
            ->field('po.*')
            ->with(['payments', 'itemList'])
            ->append(['pay_type_value', 'pay_terms_value', 'status_value'])
            ->page($page, $limit)
            ->order('po.id', 'desc')
            ->select();

        $purchaseIds = [];
        $operatorArr = [];
        $supidArr = [];
        foreach ($result as $value) {
            $operatorArr[] = $value->owner;
            $operatorArr[] = $value->updater;
            $operatorArr[] = $value->creator;
            $operatorArr[] = $value->signatoryid;
            $partnerArr = explode(',', $value->partner ?? []);
            foreach ($partnerArr as $v) {
                $operatorArr[] = $v;
            }
            $purchaseIds[] = $value->id;
            $supidArr[] = $value->supid;
        }

        $supidDict = [];
        $oSupplierModel = Db::name('seller_info')->whereIn('id', array_unique($supidArr))->column(['name', 'id']);
        foreach ($oSupplierModel as $item) {
            $supidDict[$item['id']] = $item['name'];
        }
        $operatorDict = [];
        $oOperator = OperatorModel::whereIn('id', array_unique($operatorArr))->column(['cname as name', 'id']);
        foreach ($oOperator as $item) {
            $operatorDict[$item['id']] = $item['name'];
        }

        $payments = Db::table('db_purchase_payment_order')
            ->whereIn('purchaseid', $purchaseIds)
            ->where('status', '=', 30)
            ->field('purchaseid, sum(pay_amount) as sum_pay_amount')
            ->group('purchaseid')
            ->select();
        $paymentsDict = [];
        foreach ($payments as $item) {
            $paymentsDict[$item['purchaseid']] = $item['sum_pay_amount'];
        }

        foreach ($result as $value) {
            $partnerArr = explode(',', $value->partner ?? []);
            $partnerName = [];
            foreach ($partnerArr as $v) {
                if (isset($operatorDict[$v])) {
                    $partnerName[] = $operatorDict[$v];
                }
            }

            $paid_amount = isset($paymentsDict[$value->id]) ? $paymentsDict[$value->id] : 0; // 获取支付已完成的金额

            // 获取订单总金额 = 采购单商品总金额 + 物流费用 + 其他金额
            $sum = $value->product_total_amount + $value->logistics_amount + $value->other_amount;
            $value->is_full_payment = $value->pay_status == 2;
            $value->gap = $value->product_total_amount + $value->other_amount - $value->pay_amount;
            $value->sum_amount = number_format($sum, 2);
            $value->show_entry = $paid_amount > 0; // 改为只要有一笔支付完成的付款单 则显示入库按钮
            $value->paid_amount = $value->pay_amount; //已付款金额
            //            $value->product_total_amount = number_format($value->product_total_amount + $value->other_amount, 2);//采购总金额
            $value->total_amount = number_format($value->product_total_amount + $value->other_amount, 2); //订单总金额
            $value->partner = implode(',', $partnerName);
            $value->paid_exist = isset($paymentsDict[$value->id]);
            $value->creator_value = $operatorDict[$value->creator] ?? '';
            $value->updater_value = $operatorDict[$value->updater] ?? '';
            $value->signatoryid_value = $operatorDict[$value->signatoryid] ?? '';
            $value->owner_value = $operatorDict[$value->owner] ?? '';
            $value->supid_value = $supidDict[$value->supid] ?? '';
            $value->purchase_goods = $value->itemList;
            foreach ($value->purchase_goods as &$goods) {
                $goods['subtotal'] = round($goods['num'] * $goods['unit_price'], 2);
            }
            unset($value['itemList']);
            unset($value['payments']);
        }

        $result = $result->toArray();
        $arrData['data'] = ['list' => $result, 'total' => $total];
        return $arrData;
    }

    /**
     * 删除单条或多条采购单数据
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delete($param)
    {
        $where = [['is_del', '=', '0'], ['id', 'in', $param['ids']]];

        $oPurchaseModel = PurchaseModel::where($where);
        $purchase = $oPurchaseModel->find();
        if (!$purchase) {
            return ['code' => 1, 'message' => '获取采购单信息失败！'];
        }
        $result = $oPurchaseModel->update(['is_del' => time()]);
        PurchaseOrdersDetailModel::whereIn('orderid', $param['ids'])->delete();
        if ($result) {
            $this->logger->logOperation($param['ids'], 'Purchase', '删除', '删除单条或多条采购单数据');
            return ['code' => 0, 'message' => '删除采购单成功！'];
        } else {
            return ['code' => 1, 'message' => '删除采购单失败！'];
        }
    }

    /**
     * 添加修改采购单
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function save($param)
    {
        Db::startTrans();
        try {
            $total_num = 0;
            $total_sum = 0;
            $action_type = 'add';
            foreach ($param['purchase_goods'] as $value) {
                $total_num += $value['num'];
                $total_sum += $value['unit_sum'];
            }

            if ($param['purchase_no'] === '' || $param['purchase_no'] === null) {
                $purchase_no = $this->get_unique_str();
            } else {
                $purchase_no = $param['purchase_no'];
            }
            $checkPurchaseModel = PurchaseModel::where([['purchase_no', '=', $purchase_no], ['is_del', '=', 0]]);
            if ($param['id']) {
                $checkPurchaseModel->where('id', '<>', $param['id']);
            }
            if ($checkPurchaseModel->find()) {
                throw new Exception("采购单编码重复！");
            }

            if ($param['id']) {
                $oPurchaseModel = PurchaseModel::find($param['id']);
                $oPurchaseModel->updater = $param['operator_id'];
                $oPurchaseModel->update_time = date('Y-m-d H:i:s', time());
                $action_type = 'edit';
            } else {
                $oPurchaseModel = new PurchaseModel();
                $oPurchaseModel->creator = $param['operator_id'];
                $oPurchaseModel->create_time = date('Y-m-d H:i:s', time());
                $oPurchaseModel->is_del = 0;
                $oPurchaseModel->status = 20;
                $oPurchaseModel->pay_status = 0;
            }

            $oPurchaseModel->supid = $param['supid'];
            $oPurchaseModel->purchase_no = $purchase_no;
            $oPurchaseModel->sales_orderno = $param['sales_orderno'];
            $oPurchaseModel->order_id = $param['order_id'];
            $oPurchaseModel->order_time = date('Y-m-d H:i:s', time());
            $oPurchaseModel->signatoryid = $param['signatoryid'];
            $oPurchaseModel->pay_type = $param['pay_type'];
            $oPurchaseModel->pay_terms = $param['pay_terms'];
            $oPurchaseModel->advance_delivery_date = $param['advance_delivery_date'];
            $oPurchaseModel->pay_num = $total_num;
            $oPurchaseModel->product_total_amount = $param['product_total_amount'];
            $oPurchaseModel->other_amount = $param['other_amount'];
            $oPurchaseModel->notes = $param['notes'];
            $oPurchaseModel->owner = $param['owner'];
            $oPurchaseModel->currency = $param['currency'];
            $oPurchaseModel->type = $param['type'] ?: null;
            $oPurchaseModel->contract_no = $param['contract_no'];

            // 获取汇率
            if ($param['currency'] == 4) {
                $fetcher = new ExchangeRateHostAPI();
                $exchange_rate = $fetcher->getRate('CNY', 'USD');
                if (!$exchange_rate) {
                    throw new Exception("获取汇率失败");
                }
                $oPurchaseModel->exchange_rate = $exchange_rate;
            }
            $oPurchaseModel->partner = is_array($param['partner']) ? implode(',', $param['partner']) : $param['partner'];
            if (!$oPurchaseModel->save()) {
                throw new Exception("采购单保存失败");
            }
            //处理采购订单详情表 - 使用增量更新策略
            $this->updatePurchaseOrderDetails($oPurchaseModel->id, $param['purchase_goods'], $param['operator_id']);

            if ($action_type == 'edit' && $oPurchaseModel->status != 20) { // 修改采购单时，判断是否修改订单状态
                $oPurchaseInfo = $this->getInfo($param);
                if ($oPurchaseInfo['code'] == 0) {
                    $oPurchaseArray = $oPurchaseInfo['data'];
                    $this->checkDiffPaymentsData($oPurchaseArray);

                    $updateData = [];
                    if ($oPurchaseArray['paid_amount'] <= 0) { // 如果已付款金额为0，则订单状态为未支付
                        $updateData['pay_status'] = 0;
                    } else {
                        if ($oPurchaseArray['product_total_amount'] + $oPurchaseArray['other_amount'] <= $oPurchaseArray['paid_amount']) { // 如果订单总金额小于等于已付款金额，则订单状态为已支付
                            $updateData['pay_status'] = 2;
                        } else {
                            $updateData['pay_status'] = 1; // 如果订单总金额大于已付款金额，则订单状态为部分支付
                        }
                    }

                    $updateData['pay_amount'] = $oPurchaseArray['paid_amount'];

                    $is_have_no_receipt = $this->checkHaveNoReceipt($oPurchaseModel->id);

                    if ($is_have_no_receipt) {
                        $updateData['status'] = 30;
                    } else {
                        $updateData['status'] = 40;
                    }

                    $oPurchaseModel->save($updateData);
                }
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage()];
        }
        $this->logger->logOperation($oPurchaseModel->id, 'Purchase', '添加/修改', '添加/修改采购单');
        return ['code' => 0, 'message' => '保存采购单成功！'];
    }


    /**
     * @describe 检查采购单是否有未入库的商品
     * @author: Bobo
     * @date: 2025-08-05 10:40:15 
     * @param [type] @required
     * @return Renderable
     */
    public function checkHaveNoReceipt($purchase_id)
    {
        $purchase_goods = PurchaseOrdersDetailModel::where('orderid', $purchase_id)->select()->toArray();
        $purchase_receipt_details = PurchaseReceiptDetails::with(['inventory', 'product'])
            ->where('purchase_orders_detail_id', 'in', array_column($purchase_goods, 'id'))
            ->where('is_del', 0)
            ->select()->toArray();

        $purchase_goods_Map = [];

        foreach ($purchase_goods as $item) {
            if (isset($purchase_goods_Map[$item['productid']])) {
                $purchase_goods_Map[$item['productid']]['num'] += $item['num'];
            } else {
                $purchase_goods_Map[$item['productid']] = $item;
            }
        }

        $merged_receipt_details = [];
        foreach ($purchase_receipt_details as $item) {
            if (isset($merged_receipt_details[$item['productid']])) {
                $merged_receipt_details[$item['productid']] += $item['number'];
            } else {
                $merged_receipt_details[$item['productid']] = $item['number'];
            }
        }
        $is_have_no_receipt = false;

        foreach ($purchase_goods_Map as $item) {
            if (isset($merged_receipt_details[$item['productid']])) {
                if ($merged_receipt_details[$item['productid']] < $item['num']) {

                    $is_have_no_receipt = true;
                    break;
                }
            } else {

                $is_have_no_receipt = true;
                break;
            }
        }
        return $is_have_no_receipt;
    }

    /**
     * 增量更新采购订单详情表
     * 
     * 该方法实现采购单商品明细的增量更新：
     * - 新增：新数据中有，老数据中没有的记录
     * - 修改：新数据中有，老数据中也有的记录（更新字段值）
     * - 删除：老数据中有，新数据中没有的记录
     * 
     * @author: Bobo
     * @date: 2025-08-04 
     * @param int $orderId 采购单ID
     * @param array $newGoods 新的商品清单 [['id' => 商品ID, 'num' => 数量, 'unit_price' => 单价, 'notes' => 备注], ...]
     * @param int $operatorId 操作人ID
     * @throws Exception
     */
    private function updatePurchaseOrderDetails($orderId, $newGoods, $operatorId)
    {

        // ========== 第一步：获取当前数据库中的明细记录 ==========
        $existingDetails = PurchaseOrdersDetailModel::where('orderid', $orderId)->select()->toArray();
        $existingDetailsMap = []; // 以明细ID为键的现有明细映射表
        foreach ($existingDetails as $detail) {
            $existingDetailsMap[$detail['id']] = $detail;
        }

        // ========== 第二步：准备新数据的映射表 ==========
        $newGoodsMap = []; // 以明细ID为键的新商品映射表
        foreach ($newGoods as $item) {
            if ($item['unit_price'] == 0) {
                throw new Exception("商品采购单价不能为0");
            }
            // 如果有detail_id说明是修改，否则是新增
            if (isset($item['detail_id']) && $item['detail_id']) {
                $newGoodsMap[$item['detail_id']] = $item;
            } else {
                $newGoodsMap['new_' . $item['id'] . '_' . uniqid()] = $item;
            }
        }
        // ========== 第三步：处理新增和修改操作 ==========
        foreach ($newGoods as $item) {
            $productId = $item['id']; // 前端传递的商品ID在id字段中
            $detailId = $item['detail_id'] ?? null;

            if ($detailId && isset($existingDetailsMap[$detailId])) {
                // 明细已存在，执行修改操作
                $existingDetail = $existingDetailsMap[$detailId];

                // 检查是否有字段发生变化
                if (
                    $existingDetail['num'] != $item['num'] ||
                    $existingDetail['unit_price'] != $item['unit_price'] ||
                    $existingDetail['notes'] != $item['notes'] ||
                    $existingDetail['order_id'] != ($item['order_id'] ?? null)
                ) {

                    // 更新现有记录
                    $updateResult = PurchaseOrdersDetailModel::where('id', $detailId)->update([
                        'num' => $item['num'],
                        'unit_price' => $item['unit_price'],
                        'notes' => $item['notes'],
                        'order_id' => $item['order_id'] ?? ''
                    ]);

                    if (!$updateResult) {
                        throw new Exception("更新采购详情单失败：明细ID {$detailId}");
                    }
                }
            } else {
                // 明细不存在，执行新增操作
                $insertData = [
                    'order_id' => $item['order_id'] ?? null,
                    'orderid' => $orderId,
                    'productid' => $productId,
                    'order_time' => date('Y-m-d H:i:s', time()), //todo 要修改成销售订单时间
                    'num' => $item['num'],
                    'unit_price' => $item['unit_price'],
                    'creator' => $operatorId,
                    'create_time' => date('Y-m-d H:i:s', time()),
                    'notes' => $item['notes'] ?? ''
                ];
                $insertResult = PurchaseOrdersDetailModel::create($insertData);
                if (!$insertResult) {
                    throw new Exception("新增采购详情单失败：商品ID {$productId}");
                }
            }
        }


        // ========== 第四步：处理删除操作 ==========
        // 找出老数据中有但新数据中没有的明细，执行删除
        foreach ($existingDetailsMap as $detailId => $existingDetail) {
            if (!isset($newGoodsMap[$detailId])) {
                // 新数据中没有这个明细，执行删除操作
                $deleteResult = PurchaseOrdersDetailModel::where('id', $detailId)->delete();
                if (!$deleteResult) {
                    throw new Exception("删除采购详情单失败：明细ID {$detailId}");
                }
            }
        }
    }



    /**
     * 获取单个采购单信息
     * @param int $id 采购单ID
     * @return array
     */
    public function getInfo($param)
    {
        $where = [['is_del', '=', '0'], ['id', '=', $param['id']]];
        $oPurchaseModel = PurchaseModel::where($where)
            ->with([
                'purchase_goods',
                'payments' => function ($query) {
                    $query->field('id,payno,status,pay_amount,purchaseid,payment_date,owner,payment_account,pay_type,attachment,responsible,proof,is_redrush,redrushed,currency')
                        ->with(['get_responsible_name'])
                        ->append(['status_value', 'payment_account_value', 'pay_type_value']);
                },
                'getSupidValue' => function ($query) {
                    $query->field('id,name');
                },
                'getSignatoryidValue' => function ($query) {
                    $query->field('id,cname');
                },

                'getOwnerValue' => function ($query) {
                    $query->field('id,cname');
                },
                'getPartnerValue' => function ($query) {
                    $query->field('id,cname');
                },
            ])
            ->find()
            ->append(['pay_type_value', 'pay_terms_value']);


        if (!$oPurchaseModel) {
            return ['code' => 1, 'message' => '获取采购单信息失败！'];
        }

        $data = $oPurchaseModel->toArray();

        $purchase_receipt_details = PurchaseReceiptDetails::with(['inventory', 'product'])
            ->where('purchase_no', $oPurchaseModel->purchase_no)
            ->where('is_del', 0)
            ->select();



        $data['purchase_receipt_details'] = $this->checkDiffReceiptData($oPurchaseModel->purchase_goods->toArray(), $purchase_receipt_details->toArray());

        $this->checkDiffPaymentsData($data);

        foreach ($data['payments'] as $key => &$value) {
            $value['payable_amount'] = Calculate::pricecalc($data['product_total_amount'], '-', $data['pay_amount']);
        }




        if ($data['partner']) {
            $partnerArr = explode(',', $data['partner']);
            $data['partner'] = array_map(function ($item) {
                return intval($item);
            }, $partnerArr);
        }
        if ($data['purchase_goods']) {
            foreach ($data['purchase_goods'] as &$value) {
                $entered_num = 0;
                if ($value['receipt']) {
                    foreach ($value['receipt'] as $item) {
                        $entered_num += $item['number'];
                    }
                }
                $value['entered_num'] = $entered_num;
                unset($value['receipt']);
            }
        }

        return ['code' => 0, 'message' => 'success', 'data' => $data];
    }


    /**
     * 
     * 该方法用于比较采购单商品清单与入库明细数据的差异，判断是否需要显示红冲入库单
     * 主要逻辑：
     * 1. 将相同商品ID的入库明细数据进行合并（累加数量）
     * 2. 比较合并后的入库数量与采购单中的数量
     * 3. 如果入库数量大于采购数量，则标记需要显示红冲入库单
     * 
     * @author: Bobo
     * @date: 2025-07-31 16:37:18 
     * @param array $purchase_goods 采购单商品清单 [['productid' => 商品ID, 'num' => 采购数量, ...], ...]
     * @param array $purchase_receipt_details 入库明细数据 [['productid' => 商品ID, 'number' => 入库数量, ...], ...]
     * @return array 处理后的入库明细数据，包含红冲标记信息
     */
    public function checkDiffReceiptData(array $purchase_goods, array $purchase_receipt_details)
    {
        // ========== 第一步：将采购明细转换为以detail_id为键的映射表 ==========
        $purchase_goods_map = [];
        foreach ($purchase_goods as $goods) {
            $detail_id = $goods['detail_id'];
            $purchase_goods_map[$detail_id] = $goods;
        }

        // ========== 第二步：按采购明细ID合并入库数量（包括红冲数量） ==========
        $merged_receipt_by_detail = [];
        foreach ($purchase_receipt_details as $receipt_detail) {
            $purchase_orders_detail_id = $receipt_detail['purchase_orders_detail_id'];

            if (!isset($merged_receipt_by_detail[$purchase_orders_detail_id])) {
                $merged_receipt_by_detail[$purchase_orders_detail_id] = [
                    'total_number' => 0,
                    'details' => []
                ];
            }

            // 累加入库数量（包括负数的红冲数量）
            $merged_receipt_by_detail[$purchase_orders_detail_id]['total_number'] += $receipt_detail['number'];
            $merged_receipt_by_detail[$purchase_orders_detail_id]['details'][] = $receipt_detail;
        }

        // ========== 第三步：处理每条入库明细，检查是否需要红冲 ==========
        foreach ($purchase_receipt_details as &$receipt_detail) {
            $purchase_orders_detail_id = $receipt_detail['purchase_orders_detail_id'];

            // 初始化红冲标记字段
            $receipt_detail['is_show_red_ink_receipt'] = false;
            $receipt_detail['max_red_ink_receipt_number'] = 0;

            // 跳过已经是红冲记录的数据（number < 0）
            if ($receipt_detail['number'] < 0) {
                continue;
            }

            // 获取该采购明细的净入库数量
            $net_receipt_number = $merged_receipt_by_detail[$purchase_orders_detail_id]['total_number'];

            // 情况1：该入库明细对应的采购明细在当前采购单中不存在（可能被删除）
            if (!isset($purchase_goods_map[$purchase_orders_detail_id])) {
                // 如果净入库数量大于0，则可以红冲
                if ($net_receipt_number > 0) {
                    $receipt_detail['is_show_red_ink_receipt'] = true;
                    $receipt_detail['max_red_ink_receipt_number'] = $net_receipt_number;
                }
                continue;
            }

            // 情况2：净入库数量大于采购数量（超量入库）
            $purchase_num = $purchase_goods_map[$purchase_orders_detail_id]['num'];
            if ($net_receipt_number > $purchase_num) {
                // 标记需要显示红冲入库单，红冲数量为超出的部分
                $receipt_detail['is_show_red_ink_receipt'] = true;
                $receipt_detail['max_red_ink_receipt_number'] = $net_receipt_number - $purchase_num;
                continue;
            }

            // 情况3：净入库数量等于或小于采购数量（正常情况）
            // 不需要红冲，保持默认值 false 和 0
        }

        // ========== 第四步：处理仓库名称信息 ==========
        // 处理仓库ID，可能是逗号分隔的字符串
        $all_wid = [];
        foreach ($purchase_receipt_details as $detail) {
            if (!empty($detail['wid'])) {
                // 如果wid包含逗号，则分割成多个ID
                $wids = explode(',', $detail['wid']);
                foreach ($wids as $wid) {
                    $wid = trim($wid);
                    if ($wid) {
                        $all_wid[] = $wid;
                    }
                }
            }
        }
        $all_wid = array_unique($all_wid);
        $all_wid_name = DB::name('warehouse')->whereIn('id', $all_wid)->column('name', 'id');

        // 为每条入库明细设置仓库名称
        foreach ($purchase_receipt_details as &$item) {
            // 处理仓库名称，可能包含多个仓库
            if (!empty($item['wid'])) {
                $wids = explode(',', $item['wid']);
                $warehouse_names = [];
                foreach ($wids as $wid) {
                    $wid = trim($wid);
                    if ($wid && isset($all_wid_name[$wid])) {
                        $warehouse_names[] = $all_wid_name[$wid];
                    }
                }
                $item['warehouse_name'] = implode(',', $warehouse_names);
            } else {
                $item['warehouse_name'] = '';
            }
        }

        // 返回处理后的原始入库明细数据（重新索引数组）
        return array_values($purchase_receipt_details);
    }

    /**
     * 检查付款单差异数据
     * @author: Bobo
     * @date: 2025-08-04 10:48:04 
     * @param [type] @required
     * @return Renderable
     */
    private function checkDiffPaymentsData(&$purchase)
    {
        $payments = array_filter($purchase['payments'], function ($item) {
            return $item['status'] == 30;
        });
        $paid_amount = 0;
        $fetcher = new ExchangeRateHostAPI();
        foreach ($payments as $payment) {
            if ($payment['currency'] == $purchase['currency']) {
                $paid_amount += $payment['pay_amount'];
            } else {
                $exchange_rate = $fetcher->getRateByCurrencyId($payment['currency'], $purchase['currency']);
                $paid_amount += Calculate::pricecalc($payment['pay_amount'], '*', $exchange_rate);
            }
        }
        $paid_amount = round($paid_amount, 2);
        $total_amount = round($purchase['product_total_amount'] + $purchase['other_amount'], 2);
        $purchase['is_show_red_ink_payments'] = $total_amount < $paid_amount;
        $purchase['max_red_ink_payments_amount'] = round(abs($total_amount - $paid_amount), 2);
        $purchase['paid_amount'] = round($paid_amount, 2); // 对应订单币种的已付款金额
    }

    public function getFieldEnum($field)
    {
        $model = new PurchaseModel();
        $res = $model->getFieldEnum($field);

        // 处理返回数据，确保关联数组的key不会丢失
        if (is_array($res)) {
            foreach ($res as $key => $value) {
                if (is_array($value) && !empty($value)) {
                    $keys = array_keys($value);
                    // 检查是否是连续数字key且从0开始（这种情况会被转换为JSON数组）
                    $isSequentialFromZero = true;
                    for ($i = 0; $i < count($keys); $i++) {
                        if ($keys[$i] !== $i) {
                            $isSequentialFromZero = false;
                            break;
                        }
                    }
                    // 如果是连续数字key从0开始，强制转换为对象格式保持key
                    if ($isSequentialFromZero && is_numeric($keys[0])) {
                        $res[$key] = (object)$value;
                    }
                }
            }
        }

        return [
            'code' => 0,
            'data' => $res
        ];
    }

    /**
     * 采购单审核
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function examine($param)
    {
        $where = [
            ['id', '=', $param['id']],
            ['is_del', '=', 0],
            ['status', '=', 10]
        ];
        $oPurchaseModel = PurchaseModel::where($where)->find();
        if (!$oPurchaseModel) {
            return ['code' => 1, 'message' => '获取采购单信息失败！'];
        }
        $oPurchaseModel->status = 20;
        $oPurchaseModel->info = $param['info'];
        if ($oPurchaseModel->save()) {
            $this->logger->logOperation($oPurchaseModel->id, 'Purchase', '审核', '审核采购单');
            return ['code' => 0, 'message' => '采购单审核成功！'];
        }
    }

    /**
     * 采购单确认付款
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function confirm($param)
    {
        $purchasewhere = [
            ['id', '=', $param['id']],
            ['is_del', '=', 0],
            ['status', '=', 20]
        ];
        $oPurchaseModel = PurchaseModel::where($purchasewhere)->find();
        if (!$oPurchaseModel) {
            return ['code' => 1, 'message' => '获取采购单信息失败！'];
        }
        $checkPaid = PurchasePaymentOrder::where([
            ['is_del', '=', 0],
            ['purchaseid', '=', $param['id']],
            ['status', '<>', 30]
        ])->find();
        if ($checkPaid) {
            return ['code' => 1, 'message' => '该采购单还有付款单未付款！'];
        }
        $paymentWhere = [
            ['is_del', '=', 0],
            ['purchaseid', '=', $param['id']]
        ];
        $check_sum = PurchasePaymentOrder::where($paymentWhere)->sum('pay_amount');
        if ($check_sum != $oPurchaseModel->product_total_amount) {
            return ['code' => 1, 'message' => '付款单金额与采购单金额不相等！'];
        }
        $oPurchaseModel->status = 30;
        $oPurchaseModel->updater = $param['operator_id'];
        $oPurchaseModel->update_time = date('Y-m-d H:i:s', time());
        if ($oPurchaseModel->save()) {
            $this->logger->logOperation($oPurchaseModel->id, 'Purchase', '确认付款', '确认付款采购单');
            return ['code' => 0, 'message' => '确认付款成功！'];
        }
    }

    /**
     * 采购商品入库操作
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function entry($param)
    {

        Db::startTrans();
        try {
            $oPurchaseOrdersDetailModel = PurchaseOrdersDetailModel::where('id', $param['id'])->find();
            $notes = $oPurchaseOrdersDetailModel->notes;
            if (!$oPurchaseOrdersDetailModel) {
                throw new Exception("未找到数据！");
            }

            $checkBatch = InventoryModel::where('inbound_batch', $param['arrival_batch'])->find();
            if ($checkBatch) {
                throw new Exception("批次号重复！");
            }
            //查询该采购单 入库数量 和 已入库数量 是否对应
            $oPurchaseReceiptDetails = PurchaseReceiptDetails::where('purchase_orders_detail_id', $param['id'])->find();
            // 剩余采购数量
            $surplus = $oPurchaseOrdersDetailModel->num - ($oPurchaseReceiptDetails ? $oPurchaseReceiptDetails->number : 0);
            if ($param['entry_num'] > $surplus) {
                throw new Exception("入库数量大于采购数量！");
            }

            // 通过商品id 仓库获取库存信息
            $oInventoryExist = true;
            $where = [
                ['productid', '=', $oPurchaseOrdersDetailModel->productid],
                ['is_del', '=', 0],
                //                ['arrival_batch', '=', $param['futures'] ? $param['arrival_batch'] : ''],// 考虑是否要删掉
                ['is_futures', '=', $param['futures'] ? 1 : 0]
            ];
            if (is_array($param['warehouse'])) {
                $where[] = ['wid', '=', implode(',', $param['warehouse'])];
            } else {
                $where[] = ['wid', '=', $param['warehouse']];
            }

            $oPurchaseModel = PurchaseModel::where('id', $oPurchaseOrdersDetailModel->orderid)->find();
            if (!$oPurchaseModel) {
                throw new Exception("未找到采购数据！");
            }

            $oInventoryModel = null; //全部为新增
            if (!$oInventoryModel) {
                $oInventoryExist = false;
                $oInventoryModel = new InventoryModel();
                $oInventoryModel->creator = $param['operator_id'];
                $oInventoryModel->create_time = date('Y-m-d H:i:s', time());
            } else {
                $oInventoryModel->updater = $param['operator_id'];
                $oInventoryModel->update_time = date('Y-m-d H:i:s', time());
            }
            // 更新库存表数据
            $oInventoryModel->productid = $oPurchaseOrdersDetailModel->productid;
            $oInventoryModel->wid = is_array($param['warehouse']) ? implode(',', $param['warehouse']) : $param['warehouse'];
            $oInventoryModel->available_qty = $oInventoryExist ? ($oInventoryModel->available_qty + $param['entry_num']) : $param['entry_num'];
            $oInventoryModel->convertible_qty = $param['futures'] == 0 ? 0 : ($oInventoryExist ? ($oInventoryModel->convertible_qty + $param['entry_num']) : $param['entry_num']);
            $oInventoryModel->initial_qty = $oInventoryExist ? ($oInventoryModel->initial_qty + $param['entry_num']) : $param['entry_num'];
            $oInventoryModel->is_futures = $param['futures'];
            $oInventoryModel->inbound_batch = $param['arrival_batch'];
            $oInventoryModel->arrival_date = $param['delivery_date'];
            $oInventoryModel->real_arrival_date = $param['delivery_date'];
            $oInventoryModel->purchase_currency = $oPurchaseModel->currency;
            $oInventoryModel->purchase_price = $oPurchaseOrdersDetailModel->unit_price;
            $oInventoryModel->source_table = 'purchase_orders';
            $oInventoryModel->source_id = $param['id'];
            $oInventoryModel->ccname_ids = is_array($param['ccname_ids']) ? implode(',', $param['ccname_ids']) : $param['ccname_ids'];

            if (!$oInventoryModel->save()) {
                throw new Exception("入库失败！");
            }

            $warehouse =  is_array($param['warehouse']) ? $param['warehouse'] : explode(',', $param['warehouse']);
            #设置库存价格
            foreach ($warehouse as $w) {
                $inventory_param = [
                    'productid' => $oInventoryModel->productid,
                    'is_futures' => $oInventoryModel->is_futures,
                    'arrival_date' => $oInventoryModel->arrival_date,
                ];
                $inventoryInfo = InventoryModel::where($inventory_param)->whereFindInSet('wid', $w)->where('id', '<>', $oInventoryModel->id)->find();
                if ($inventoryInfo) {
                    (new \app\common\service\Inventory())->insertInventoryPrice($inventoryInfo, $oInventoryModel->id, $w, $param['operator_id']);
                }
            }

            // 判断采购单是否全部支付完毕 完毕则将订单状态更新为采购完成
            $check_sum = PurchasePaymentOrder::where([
                ['is_del', '=', 0],
                ['purchaseid', '=', $oPurchaseOrdersDetailModel->orderid],
                ['status', '=', 30]
            ])->sum('pay_amount');

            $supname = Db::name('seller_info')->where('id', $oPurchaseModel->supid)->field('name')->find();

            // 执行入库操作
            $newPurchaseReceiptDetails = new PurchaseReceiptDetails();
            $newPurchaseReceiptDetails->purchase_orders_detail_id = $param['id'];
            $newPurchaseReceiptDetails->inventory_id = $oInventoryModel->id;
            $newPurchaseReceiptDetails->number = $param['entry_num'];
            $newPurchaseReceiptDetails->remark = $param['remark'];
            $newPurchaseReceiptDetails->creator = $param['operator_id'];
            $newPurchaseReceiptDetails->create_time = date('Y-m-d H:i:s', time());
            $newPurchaseReceiptDetails->supname = $supname['name'] ?? '';
            $newPurchaseReceiptDetails->sales_orderno = $oPurchaseModel->sales_orderno;
            $newPurchaseReceiptDetails->purchase_no = $oPurchaseModel->purchase_no;
            $newPurchaseReceiptDetails->cost = $oPurchaseOrdersDetailModel->unit_price;
            $newPurchaseReceiptDetails->order_time = $oPurchaseModel->order_time;

            // 判断该采购单是否全部入库完成  全部入库完成则 更新采购单状态
            $entered_num = $param['entry_num'];
            $oPurchaseOrdersDetailModel = PurchaseOrdersDetailModel::where('orderid', $oPurchaseOrdersDetailModel->orderid);
            $entry_num = $oPurchaseOrdersDetailModel->sum('num'); //需要入库的数量
            $detail_ids = $oPurchaseOrdersDetailModel->column('id');
            $entered_num += PurchaseReceiptDetails::where('purchase_orders_detail_id', 'in', $detail_ids)->sum('number');

            if (($oPurchaseModel->product_total_amount == $check_sum) && ($entry_num == $entered_num)) {
                // 将采购订单状态更新为 采购完成
                $oPurchaseModel->status = 40;
                $oPurchaseModel->creator = $param['operator_id'];
                $oPurchaseModel->creat_time = date('Y-m-d H:i:s', time());
                if (!$oPurchaseModel->save()) {
                    throw new Exception("更新采购单状态失败！");
                }
            }

            if (!$newPurchaseReceiptDetails->save()) {
                throw new Exception("入库操作失败！");
            }

            // 执行库存盘点(库存类型为现货的时候 更新)
            if ($param['futures'] == 0) {
                Warehouse::productSoldStat($oInventoryModel->productid, $param['warehouse'], $param['entry_num'], 0, 0);
            }
            #生成调拨单
            if ($param['futures'] == 1) {
                $logistics_param = [
                    'company_id' => 0,
                    'arrival_date' => $param['delivery_date'],
                    'real_arrival_date' => $param['delivery_date'],
                    'logistics_no' => '',
                    'logistics_voucher' => '',
                    'cost' => [],
                    'notes' => $notes,
                    'transaction_currency_id' => null,
                    'ship_date' => date('Y-m-d'),
                ];
                $logistics_id = (new Inventory())->insertLogisticOrderData($logistics_param, 3);
                $logistics_iterm_param = [
                    'logistics_order_id' => $logistics_id,
                    'order_id' => $newPurchaseReceiptDetails->id,
                    'product_id' => $oInventoryModel->productid,
                    'warehouse_id' => '',
                    'number' => $param['entry_num'],
                    'to_warehouse_id' => $param['warehouse'],
                    'create_time' => date("Y-m-d H:i:s"),
                    'inventory_id' => null,
                    'to_inventory_id' => $oInventoryModel->id,
                ];
                $oInventoryModel = new \app\admin\model\LogisticsOrderItem();
                $oInventoryModel->insert($logistics_iterm_param);
            }
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage() . '行：' . $e->getLine()];
        }
        $this->logger->logOperation($param['id'], 'Purchase', '入库', '库存入库');
        return ['code' => 0, 'message' => '数据入库成功！'];
    }

    /**
     * 采购批量入库操作
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function batchEntry($param)
    {
        Db::startTrans();
        try {
            $oPurchaseModel = PurchaseModel::where([['is_del', '=', 0], ['status', '=', 30], ['id', '=', $param['id']]])->with(['purchase_goods'])->find();
            if (!$oPurchaseModel) {
                throw new Exception("未找到采购数据！");
            }
            $checkBatch = InventoryModel::where('inbound_batch', $param['arrival_batch'])->find();
            if ($checkBatch) {
                throw new Exception("批次号重复！");
            }
            $data = $oPurchaseModel->toArray();
            $notes = $data['notes'];
            if (!isset($data['purchase_goods']) || !$data['purchase_goods']) {
                throw new Exception("未找到采购商品数据！");
            }
            $purchase_goods = $data['purchase_goods'];
            $batch_data = [];
            foreach ($purchase_goods as &$value) {
                $entered_num = 0;
                if ($value['receipt']) {
                    foreach ($value['receipt'] as $item) {
                        $entered_num += $item['number'];
                    }
                }
                $value['entered_num'] = $entered_num;
                unset($value['receipt']);
                if ($value['num'] - $entered_num > 0) {
                    $batch_data[] = [
                        'orderid' => $value['orderid'],
                        'detail_id' => $value['detail_id'],
                        'num' => $value['num'] - $entered_num, // 需要入库数量
                        'unit_price' => $value['unit_price'],
                        'productid' => $value['productid'],
                        'warehouse' => $param['warehouse']
                    ];
                }
            }
            // 遍历每个采购商品 获取剩余采购数量

            $insertData = [];
            $logistics_iterm_param = [];
            foreach ($batch_data as $item) {
                // 查询库存id
                $where = [
                    ['productid', '=', $item['productid']],
                    ['is_del', '=', 0],
                    //                    ['arrival_batch', '=', $param['futures'] ? $param['arrival_batch'] : ''],
                    ['is_futures', '=', $param['futures'] ? 1 : 0]
                ];
                if (is_array($param['warehouse'])) {
                    $where[] = ['wid', '=', implode(',', $param['warehouse'])];
                } else {
                    $where[] = ['wid', '=', $param['warehouse']];
                }

                $oPurchaseModel = PurchaseModel::where('id', $item['orderid'])->find();
                if (!$oPurchaseModel) {
                    throw new Exception("未找到采购数据！");
                }

                $oInventoryModel = null; //全部为新增
                $oInventoryExist = true;
                if (!$oInventoryModel) {
                    $oInventoryExist = false;
                    $oInventoryModel = new InventoryModel();
                    $oInventoryModel->creator = $param['operator_id'];
                    $oInventoryModel->create_time = date('Y-m-d H:i:s', time());
                } else {
                    $oInventoryModel->updater = $param['operator_id'];
                    $oInventoryModel->update_time = date('Y-m-d H:i:s', time());
                }
                // 更新库存表数据
                $oInventoryModel->productid = $item['productid'];
                $oInventoryModel->wid = is_array($param['warehouse']) ? implode(',', $param['warehouse']) : $param['warehouse'];
                $oInventoryModel->available_qty = $oInventoryExist ? ($oInventoryModel->qty + $item['num']) : $item['num'];
                $oInventoryModel->inbound_batch = $param['arrival_batch'];
                $oInventoryModel->convertible_qty = $param['futures'] == 0 ? 0 : $item['num'];
                $oInventoryModel->initial_qty = $oInventoryExist ? ($oInventoryModel->initial_qty + $item['num']) : $item['num'];
                $oInventoryModel->arrival_date = $param['delivery_date'];
                $oInventoryModel->real_arrival_date = $param['delivery_date'];
                $oInventoryModel->is_futures = $param['futures'];
                $oInventoryModel->purchase_currency = $oPurchaseModel->currency;
                $oInventoryModel->purchase_price = $item['unit_price'];
                $oInventoryModel->source_table = 'purchase_orders';
                $oInventoryModel->source_id = $param['id'];
                $oInventoryModel->ccname_ids = is_array($param['ccname_ids']) ? implode(',', $param['ccname_ids']) : $param['ccname_ids'];

                if (!$oInventoryModel->save()) {
                    throw new Exception("入库失败！");
                }

                $warehouse =  is_array($param['warehouse']) ? $param['warehouse'] : explode(',', $param['warehouse']);
                #设置库存价格
                foreach ($warehouse as $w) {
                    $inventory_param = [
                        'productid' => $oInventoryModel->productid,
                        'is_futures' => $oInventoryModel->is_futures,
                        'arrival_date' => $oInventoryModel->arrival_date,
                    ];
                    $inventoryInfo = InventoryModel::where($inventory_param)->whereFindInSet('wid', $w)->find();

                    (new \app\common\service\Inventory())->insertInventoryPrice($inventoryInfo, $oInventoryModel->id, $w, $param['operator_id']);
                }

                $supname = Db::name('seller_info')->where('id', $oPurchaseModel->supid)->field('name')->find();
                $insertData = [
                    'purchase_orders_detail_id' => $item['detail_id'],
                    'inventory_id' => $oInventoryModel->id,
                    'supname' => $supname['name'] ?? '',
                    'sales_orderno' => $oPurchaseModel->sales_orderno,
                    'purchase_no' => $oPurchaseModel->purchase_no,
                    'cost' => $item['unit_price'],
                    'order_time' => $oPurchaseModel->order_time,
                    'number' => $item['num'],
                    'remark' => '',
                    'creator' => $param['operator_id'],
                    'create_time' => date('Y-m-d H:i:s', time())
                ];
                $purchaseReceiptId = (new PurchaseReceiptDetails())->insertGetId($insertData);

                // 执行库存盘点(库存类型为现货的时候 更新)
                if ($param['futures'] == 0) {
                    Warehouse::productSoldStat($oInventoryModel->productid, $param['warehouse'], $item['num'], 0, 0);
                }

                if ($param['futures'] == 1) {
                    $logistics_iterm_param[] = [
                        'product_id' => $oInventoryModel->productid,
                        'warehouse_id' => '',
                        'order_id' => $purchaseReceiptId,
                        'number' => $item['num'],
                        'to_warehouse_id' => $param['warehouse'],
                        'create_time' => date("Y-m-d H:i:s"),
                        'inventory_id' => null,
                        'to_inventory_id' => $oInventoryModel->id,
                    ];
                }
            }
            // 将采购订单状态更新为采购完成
            $oPurchaseModel->status = 40;
            $oPurchaseModel->creator = $param['operator_id'];
            $oPurchaseModel->creat_time = date('Y-m-d H:i:s', time());
            if (!$oPurchaseModel->save()) {
                throw new Exception('更新采购订单状态失败!');
            }
            // todo 要加入库存记录

            #生成调拨单
            if ($param['futures'] == 1) {
                $logistics_param = [
                    'company_id' => 0,
                    'arrival_date' => $param['delivery_date'],
                    'real_arrival_date' => $param['delivery_date'],
                    'logistics_no' => '',
                    'logistics_voucher' => '',
                    'cost' => [],
                    'notes' => $notes,
                    'transaction_currency_id' => null,
                    'ship_date' => date('Y-m-d'),
                ];
                $logistics_id = (new Inventory())->insertLogisticOrderData($logistics_param, 3);
                if ($logistics_iterm_param) {
                    foreach ($logistics_iterm_param as &$vvv) {
                        $vvv['logistics_order_id'] = $logistics_id;
                    }
                }
                $oInventoryModel = new \app\admin\model\LogisticsOrderItem();
                $oInventoryModel->insertAll($logistics_iterm_param);
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage()];
        }
        $this->logger->logOperation($param['id'], 'Purchase', '批量入库', '批量入库');
        return ['code' => 0, 'message' => '数据入库成功！'];
    }

    public function get_unique_str()
    {
        $currentDate = date('Ymd');
        $uniqueIdentifier = uniqid('');
        $finalCode = $currentDate . $uniqueIdentifier;
        return $finalCode;
    }


    /**
     *
     */
    public function salesOrderNo($param)
    {
        $order = Order::where('is_del', '=', 0)->where('order_no', 'like', "%{$param['order_no']}%")->field('id,order_no')->select();
        $data = [];
        if ($order) {
            foreach ($order as $v) {
                $data[] = [
                    'value' => $v['id'],
                    'label' => $v['order_no']
                ];
            }
        }
        return ['code' => 0, 'message' => 'ok', 'data' => $data];
    }


    /* 获取订单号商品 */
    public function getOrderProduct($param)
    {

        // 普通订单排除订单状态为：已取消 待收货 已完成
        $order = Order::with([
            'items' => function ($query) {
                $query->field('id,order_id,product_id,quantity')->where('is_del', '=', 0);
            }
        ])
            ->where('is_del', '=', 0)
            ->where('id', '=', $param['order_id'])->field('id,order_no')->select();


        $quantity = [];
        $product_ids = [];
        if ($order) {
            foreach ($order as $v) {
                foreach ($v['items'] as $vv) {
                    $product_ids[] = $vv['product_id'];
                    if (isset($quantity[$vv['product_id']])) {
                        $quantity[$vv['product_id']] += $vv['quantity'];
                    } else {
                        $quantity[$vv['product_id']] = $vv['quantity'];
                    }
                }
            }
        }

        if (count($product_ids) > 0) {
            $product_ids = array_unique($product_ids);
        }


        if (count($product_ids) > 0) {
            $product_ids = array_unique($product_ids);
            $where[] = ['id', 'in', $product_ids];
        } else {
            return ['code' => 0, 'message' => 'success'];
        }

        // $where[] = ['type', '=', 1];
        $where[] = ['is_del', '=', 0];

        $arrData = ['code' => 0, 'message' => 'success'];
        $oProductModel = ProductModel::where($where);
        $total = $oProductModel->count();
        $result = $oProductModel
            ->with(['creator', 'get_category_value', 'get_brand_value', 'model_value' => function ($query) {
                return $query->field('id,model_name');
            }])
            ->append(['condition_text', 'is_advance_text', 'unit_value'])
            ->order('id', 'desc')
            ->select();

        foreach ($result as &$value) {
            $value->brand_value = $value->brand_value ?? '';
            if (isset($value->model_value)) {
                $value->model_value = $value->model_value->model_name;
            } else {
                $value->model_value = '';
            }

            $ProductModel = new ProductModel();
            /* 电源 */
            if ($value->has_powersource) {
                $has_powersource = $ProductModel->getAttributes('has_powersource');
                $value->has_powersource_name = array_key_exists($value->has_powersource, $has_powersource) ? $has_powersource[$value->has_powersource] : '';
            } else {
                $value->has_powersource_name = '';
            }

            /* 电源线 */
            if ($value->has_powerline) {
                $has_powerline = $ProductModel->getAttributes('has_powerline');
                $value->has_powerline_name = array_key_exists($value->has_powerline, $has_powerline) ? $has_powerline[$value->has_powerline] : '';
            } else {
                $value->has_powerline_name = '';
            }

            /* 规格 */
            if ($value->powerline_standards) {
                $powerline_standards = $ProductModel->getAttributes('powerline_standards');
                $value->powerline_standards_name = array_key_exists($value->powerline_standards, $powerline_standards) ? $powerline_standards[$value->powerline_standards] : '';
            } else {
                $value->powerline_standards_name = '';
            }
            if (isset($quantity[$value->id])) {
                $value->quantity = $quantity[$value->id];
            } else {
                $value->quantity =  $quantity[$value->id];
            }
        }
        $arrData['data'] = ['list' => $result->toArray(), 'total' => $total];
        return $arrData;
    }

    /**
     * @describe 红冲
     * @author: Bobo
     * @date: 2025-08-01 16:38:31 
     * @param [type] @required
     * @return Renderable
     */
    public function redInkReversal($param)
    {
        $oPurchaseModel = PurchaseModel::where('id', $param['id'])->with(['payments'])->find();
        if (!$oPurchaseModel) {
            return ['code' => 1, 'message' => '采购订单不存在'];
        }
        if (1 == $param['type']) {
            return $this->redInkReversalByPurchasePayments($param, $oPurchaseModel);
        } else if (2 == $param['type']) {
            return $this->redInkReversalByPurchaseReceipt($param, $oPurchaseModel);
        }
    }
    /**
     * @describe 红冲付款信息
     * @author: Bobo
     * @date: 2025-08-01 16:39:01 
     * @param [type] @required
     * @return Renderable
     */
    private function redInkReversalByPurchasePayments($param, $oPurchaseModel)
    {
        $oPurchasePaymentOrderModel = PurchasePaymentOrder::where('id', $param['payments_id'])->find();
        if (!$oPurchasePaymentOrderModel) {
            return ['code' => 1, 'message' => '付款单不存在'];
        }

        $oPurchaseArray = $oPurchaseModel->toArray();
        $this->checkDiffPaymentsData($oPurchaseArray);

        if ($oPurchaseArray['max_red_ink_payments_amount'] < $param['amount']) {
            return ['code' => 1, 'message' => '红冲金额大于最大红冲金额'];
        }
        $oCommon = new Common();

        Db::startTrans();
        try {
            $oPurchasePaymentOrderModel->insert([
                'status' => 30,
                'payno' =>   $oCommon->generateOrderNo($param['operator_id']),
                'currency' => $oPurchaseModel->currency,
                'pay_amount' => -$param['amount'],
                'payment_account' => $oPurchasePaymentOrderModel->payment_account,
                'pay_type' => $oPurchasePaymentOrderModel->pay_type,
                'recipient_account' => $oPurchasePaymentOrderModel->recipient_account,
                'purchaseid' => $oPurchaseModel->id,
                'owner' => $param['operator_id'],
                'payment_date' => date('Y-m-d H:i:s', time()),
                'is_redrush' => 1,
                'creator' => $param['operator_id'],
                'create_time' => date('Y-m-d H:i:s', time())
            ]);

            $oPurchasePaymentOrderModel->save([
                'redrushed' => 1,
                'updater' => $param['operator_id'],
                'update_time' => date('Y-m-d H:i:s', time())
            ]);


            $oPurchaseModel->pay_amount = Calculate::pricecalc($oPurchaseArray['paid_amount'], '-', $param['amount']);
            if ($oPurchaseModel->pay_amount <= 0) {
                $oPurchaseModel->pay_status = 0;
            } else {
                if ($oPurchaseModel->product_total_amount + $oPurchaseModel->other_amount <= $oPurchaseModel->pay_amount) {
                    $oPurchaseModel->pay_status = 2;
                } else {
                    $oPurchaseModel->pay_status = 1;
                }
            }
            $oPurchaseModel->save();
            Db::commit();
            return ['code' => 0, 'message' => '红冲成功'];
        } catch (\Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage()];
        }
    }

    /**
     * @describe 红冲入库信息
     * @author: Bobo
     * @date: 2025-08-01 16:39:01 
     * @param [type] @required
     * @return Renderable
     */
    private function redInkReversalByPurchaseReceipt($param, $oPurchaseModel)
    {
        $oPurchaseReceiptModel = PurchaseReceiptDetails::where('id', $param['purchase_receipt_details_id'])->find();
        if (!$oPurchaseReceiptModel) {
            return ['code' => 1, 'message' => '入库明细不存在'];
        }


        $info = $this->getInfo($oPurchaseModel->toArray());

        if (!$info['data'] || !$info['data']['purchase_receipt_details']) {
            return ['code' => 1, 'message' => '采购单不存在'];
        }
        $purchase_receipt_details = array_column($info['data']['purchase_receipt_details'], null, 'id');
        if (!isset($purchase_receipt_details[$oPurchaseReceiptModel->id])) {
            return ['code' => 1, 'message' => '入库明细不存在'];
        }


        if ($param['number'] > $purchase_receipt_details[$oPurchaseReceiptModel->id]['max_red_ink_receipt_number']) {
            return ['code' => 1, 'message' => '红冲数量大于入库数量'];
        }

        $inventory = InventoryModel::where('id', $oPurchaseReceiptModel->inventory_id)->find();
        if (!$inventory) {
            return ['code' => 1, 'message' => '库存不存在'];
        }



        Db::startTrans();
        try {

            $insert_id = $oPurchaseReceiptModel->insertGetId([
                'supname' => $oPurchaseReceiptModel->supname,
                'sales_orderno' => $oPurchaseReceiptModel->sales_orderno,
                'purchase_orders_detail_id' => $oPurchaseReceiptModel->purchase_orders_detail_id,
                'purchase_no' => $oPurchaseReceiptModel->purchase_no,
                'cost' => $oPurchaseReceiptModel->cost,
                'order_time' => $oPurchaseReceiptModel->order_time,
                'inventory_id' => $oPurchaseReceiptModel->inventory_id,
                'number' => -$param['number'],
                'is_redrush' => 1,
                'remark' => $oPurchaseReceiptModel->remark . '红冲入库',
                'creator' => $param['operator_id'],
                'create_time' => date('Y-m-d H:i:s', time())
            ]); //新增红冲入库单


            $oPurchaseReceiptModel->save([
                'redrushed' => 1
            ]); //修改入库单状态为红冲


            $remark = '红冲入库';
            $remark .= '原始 initial_qty :' . $inventory->initial_qty;
            $remark .= '原始 available_qty :' . $inventory->available_qty;
            $remark .= '红冲数量 :' . $param['number'];
            $remark .= '红冲后 initial_qty :' . ($inventory->initial_qty - $param['number']);
            $remark .= '红冲后 available_qty :' . ($inventory->available_qty - $param['number']);
            DB::name('inventory_change_record')->insert([
                'inventory_id' => $inventory->id,
                'business_tabel_name' => 'purchase_receipt_details',
                'business_table_id' => $insert_id,
                'business' => '红冲入库',
                'number' => -$param['number'],
                'remark' => $remark,
                'creator' => $param['operator_id'],
                'create_time' => date('Y-m-d H:i:s', time())
            ]); //新增库存变更记录mar

            $all_inventory = Db::table('db_inventory')
                ->field([
                    'productid as product_id',
                    'arrival_date',
                    'GROUP_CONCAT(DISTINCT real_arrival_date) as arrival_date',
                    'is_futures',
                    'wid',
                    'allow_zero_stock_sale',
                    'SUM(available_qty - lock_qty) as quantity',
                    'GROUP_CONCAT(id) as inventory_ids' // 库存ID集合
                ])
                ->group('productid, wid, arrival_date, is_futures, allow_zero_stock_sale')
                ->whereRaw(' allow_zero_stock_sale = 1 or (available_qty > lock_qty)')
                ->where([
                    'productid' => $inventory->productid,
                    'wid' => $inventory->wid,
                    'arrival_date' => $inventory->arrival_date,
                    'is_futures' => $inventory->is_futures,
                ])
                ->find(); // 全部库存真实可用数量

            if (!$all_inventory) {
                $all_inventory['quantity'] = 0;
            }
            $affects_order_quantity = $param['number'] - $all_inventory['quantity']; // 影响订单数量

            if ($affects_order_quantity > 0) { // 找到相关订单修改订单状态为异常
                // 查询订单明细
                $order_item = Order::name('order_item')
                    ->alias('oi')
                    ->join('order', 'order.id = oi.order_id')
                    ->where([
                        'oi.product_id' => $inventory->productid,
                        'oi.warehouse_id' => $inventory->wid,
                        'oi.arrival_date' => $inventory->arrival_date,
                        'oi.is_futures' => $inventory->is_futures,
                        'oi.is_del' => 0
                    ])
                    ->where('order.pay_status', 'in', [3, 4]) // 订单状态，已支付 部分支付
                    ->where('order.status', 'in', [10, 20, 30, 40]) // 订单状态 待支付 审核中 待发货 待收货
                    ->field('oi.id,oi.quantity,oi.order_id,oi.exceptionstatus,order.exceptionstatus,order.owner,order.partner,order.signatory,order.order_no')
                    ->order('order.pay_time asc')
                    ->select();

                if (!$order_item) {
                    throw new \Exception('未找到相关订单');
                }

                $send_order_arr = [];
                foreach ($order_item as $v) {
                    if ($affects_order_quantity <= 0) {
                        break;
                    }
                    $v->save(['exceptionstatus' => 1]); // 订单明细异常状态为1
                    $order = Order::where('id', $v['order_id'])->find();
                    if ($order) {
                        if ($order->exceptionstatus) {
                            if (strpos($order->exceptionstatus, '1') === false) { // 如果订单异常状态中不包含1，则添加1
                                $order->save(['exceptionstatus' => $order->exceptionstatus . ',1']);
                            }
                        } else {
                            $order->save(['exceptionstatus' => '1']);
                        }
                    }
                    $send_order_arr[$v['order_id']] = [
                        'id' => $v['order_id'],
                        'owner' => $v['owner'],
                        'partner' => $v['partner'],
                        'signatory' => $v['signatory'],
                        'order_no' => $v['order_no']
                    ];
                    $affects_order_quantity -= $v['pending_quantity'];
                }

                if (count($send_order_arr) > 0) {
                    $notificationService = new CompleteNotificationService();
                    foreach ($send_order_arr as $v_send) {
                        $partner = $v_send['partner'] ? explode(',', $v_send['partner']) : [];
                        $recipients = array_unique(array_merge($partner, [$v_send['owner'], $v_send['signatory']]));
                        $content = "您负责的订单库存异常，请及时跟进\n\n";
                        $content .= "订单编码：{$v_send['order_no']}";
                        $notificationService->send('order_exceptionstatus', $v_send, $recipients, $content);
                    }
                }
            }

            if ($inventory->is_futures > 0) { // 期货库存
                $inventory->save([
                    'initial_qty' => Db::raw('initial_qty - ' . $param['number']),
                    'available_qty' => Db::raw('available_qty - ' . $param['number']),
                    'convertible_qty' => Db::raw('convertible_qty - ' . $param['number']),
                    'updater' => $param['operator_id'],
                    'update_time' => date('Y-m-d H:i:s', time())
                ]); // 更新库存可用数量 
            } else {
                $inventory->save([
                    'initial_qty' => Db::raw('initial_qty - ' . $param['number']),
                    'available_qty' => Db::raw('available_qty - ' . $param['number']),
                    'updater' => $param['operator_id'],
                    'update_time' => date('Y-m-d H:i:s', time())
                ]); // 更新库存可用数量 
            }
            Db::commit();
            return ['code' => 0, 'message' => '红冲成功'];
        } catch (\Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage()];
        }
    }
}
